// Optional view for Mission eventing
// Copyright 2006 (C) Ralph Thomas

#include <view/optional.h>
#include <toolkit/application.h>
#include <binder.hpp>
#include <view/gtk/layoutable_widget.h>
#include <gtk/os_utilities.hpp>

namespace view {
	void set_state( GtkWidget* w, adobe::eve_t::iterator i, adobe::eve_t* eve, bool visible ) {
		eve->set_visible( i, visible );
		eve->evaluate( adobe::eve_t::evaluate_nested );
		if( visible ) gtk_widget_show( w );
		else gtk_widget_hide( w );
	}
	void update_value( GtkWidget* w, adobe::eve_t::iterator i, adobe::eve_t& eve, const adobe::any_regular_t& val ) {
		bool visible( false );
		if( !val.cast( visible ) ) return;
		toolkit::application::getInstance().executeInMain(
			boost::bind( &set_state, w, i, &eve, visible )
		);
	}
	adobe::widget_node_t optional_factory( const adobe::dictionary_t& params, const adobe::widget_node_t& parent, const adobe::factory_token_t& token ) {
		//
		// Extract the thing to bind to first.
		//
		adobe::any_regular_t binder = params.at( adobe::static_name_t( "bind" ) );
		//
		// We need to mark ourselves as a container.
		//
		adobe::layout_attributes_t cdata;
		cdata.placement_m = adobe::eve_t::place_column;
		//
		// We also need a fixed container to put children into so that
		// we can control visibility.
		//
		GtkWidget* container = gtk_fixed_new();
		token.client_holder_m.assemblage_m.delete_on_destruction( container );
		token.display_m.insert(parent.display_token_m, container);
		//
		// Insert ourselves into the layout engine as
		// a non-create view.
		//
		adobe::any_placeable_t* placeable(new adobe::any_placeable_t(layoutable_widget_t(container)));
		adobe::eve_t::iterator i(
			token.client_holder_m.eve_m.add_view_element( parent.eve_token_m,
					cdata,
					true,
					params,
					boost::ref(*placeable)
				)
			);
		token.client_holder_m.assemblage_m.delete_on_destruction(placeable);
		//
		// Set it to be non-visible to start with.
		//
		token.client_holder_m.eve_m.set_visible( i, false );
		//
		// Setup binder_helper_t from parameters, add to assemblage, connect, return.
		//
		adobe::binder_helper_t* bh = new adobe::binder_helper_t( token.sheet_m );
		token.client_holder_m.assemblage_m.delete_on_destruction( bh );
		bh->initialize( binder, boost::bind( &update_value, container, i, boost::ref( token.client_holder_m.eve_m ), _1 ), 0 );
		//
		// Return the new widget_node.
		//
		return adobe::widget_node_t( parent.size_m, i, container, parent.keyboard_token_m );
	}
}

